package com.cdtye.itps.cms.service.dept;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cdtye.common.authcore.constants.AuthConstants;
import com.cdtye.common.authcore.model.UserSso;
import com.cdtye.common.authcore.util.AuthHelper;
import com.cdtye.common.mybatiscore.base.BaseService;
import com.cdtye.common.webcore.enums.SysDeptTypeEnum;
import com.cdtye.common.webcore.model.po.TreePo;
import com.cdtye.common.webcore.util.ObjectUtil;
import com.cdtye.itps.cms.dao.dept.entity.SysDept;
import com.cdtye.itps.cms.dao.dept.vo.SysDeptVo;
import com.cdtye.itps.cms.mapper.dept.SysDeptMapper;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 部门 服务类
 * @author wzw
 * @date 2021-07-08
 * @Description
 * ***************************************总公司**********************************************************
 * *********************分公司0******分公司1******段1******段2**********************************************
 * **********分公司0工区0*******分公司0工区1*********段1工区0**********段2工区0********************************
 */
@Api("部门 服务")
@Service
@Slf4j
public class SysDeptService extends BaseService<SysDeptMapper, SysDept> {

    /**
     * 单位：二级所属单位（段，分公司）存在唯一的unitDeptCode
     * **************************************************A********************************************************
     * ******************AA*****************************AB*****************************AC*************************
     * *******AAA***AAB****AAC***AAD**********ABA***ABB****ABC***ABD**********ACA***ACB****ACC***ACD**************
     *
     * 1.当前用户user(总公司、局级、超级管理员)--->unitDeptCode=null ---->返回所有单位信息的信息[AA,AB,AC]
     * 2.当前用户user(段级用户、分公司用户、及其下级用户)--->unitDeptCode=AA ---->返回AA部门的信息
     * 3.当前用户user(段级用户、分公司用户、及其下级用户)--->unitDeptCode=AB ---->返回AB部门的信息
     * @return
     */
    public List<Map<String, Object>> getAllUnitDeptList(){
        //获取当前登入人的单位标识
        SysDeptVo vo = new SysDeptVo();
        String unitDeptCode = getUnitDeptCodeByLoginUser(null);
        vo.setUnitDeptCode(unitDeptCode);
        vo.setDeptTypeList(Stream.of(
                SysDeptTypeEnum.SEGMENT.getDeptType(),
                SysDeptTypeEnum.JU_GDC.getDeptType()
        ).collect(Collectors.toList()));
        return baseMapper.getDeptList(vo);
    }

    /**
     *  获取当前登入人可以管理的部门所属单位列表（段，分公司等二级直属单位）
     *  **************************************************A********************************************************
     *  ******************AA*****************************AB*****************************AC*************************
     *  *******AAA***AAB****AAC***AAD**********ABA***ABB****ABC***ABD**********ACA***ACB****ACC***ACD**************
     *
     *  1.当前用户user(总公司、局级、超级管理员)--->deptCode=A,manageDeptCode=[AA,AB] ---->返回AA,AB部门的信息
     *  2.当前用户user(段级用户、分公司用户、及其下级用户)--->deptCode=AA,manageDeptCode=[AAA,AAB,ABA] ---->返回AA,AB部门的信息
     *  3.当前用户user(段级用户、分公司用户、及其下级用户)--->deptCode=AA,manageDeptCode=[AAA,AAB,ABA,ACB] ---->返回AA,AB,AC部门的信息
     **/
    public List<Map<String, Object>> getUnitDeptListByAuth(SysDeptVo vo) {
        UserSso loginUser = AuthHelper.loginUser();
        List<String> deptNoList = new ArrayList<>();
        deptNoList.addAll(loginUser.getManageDeptCodeList());
        deptNoList.add(loginUser.getDeptCode());
        vo.setDeptCodeList(deptNoList);
        vo.setDeptTypeList(Stream.of(
                SysDeptTypeEnum.SEGMENT.getDeptType(),
                SysDeptTypeEnum.JU_GDC.getDeptType()
        ).collect(Collectors.toList()));
        return baseMapper.getUnitDeptInfoList(vo);
    }

    /**
     * 获取当前登入用户的部门和下级部门，加上可以管理的部门（但是过滤单位）
     * @param deptTypeList 部门类型列表
     * @param railType 铁路类别
     * **************************************************A********************************************************
     * ******************AA*****************************AB*****************************AC*************************
     * *******AAA***AAB****AAC***AAD**********ABA***ABB****ABC***ABD**********ACA***ACB****ACC***ACD**************
     *
     * 1.当前用户user(总公司、局级、超级管理员)--->deptCode=A,manageDeptCode=[AA,AB] ---->返回A,AA,AB,AC,AAA,AAB,AAC,AAD,ABA,ABB,ABC,ABD,ACA,ACB,ACC,ACD部门的信息
     * 2.当前用户user(段级用户、分公司用户、及其下级用户)--->deptCode=AA,manageDeptCode=[AAA,AAB,ABA] ---->返回AA,AAA,AAB,AAC,AAD,ABA部门的信息
     * 3.当前用户user(段级用户、分公司用户、及其下级用户)--->deptCode=AA,manageDeptCode=[AAA,AAB,ABA,ACB] ---->返回AA,AAA,AAB,AAC,AAD,ABA,ACB部门的信息
     * @return
     */
    public List<Map<String, Object>> getManageDeptList(List<String> deptTypeList,String railType){
        UserSso loginUser = AuthHelper.loginUser();
        HashMap<String, Object> queryMap = new HashMap<>();
        queryMap.put("deptCode", loginUser.getDeptCode());
        queryMap.put("manageDeptCodeList", loginUser.getManageDeptCodeList() == null ? Stream.of(loginUser.getDeptCode()).collect(Collectors.toList()) : loginUser.getManageDeptCodeList());
        queryMap.put("deptTypeList",deptTypeList);
        queryMap.put("railType",railType);
        List<Map<String, Object>> manageDeptList = baseMapper.getManageDeptList(queryMap);
        return manageDeptList;
    }



    /**
     * 获取当前用户所管理的接触网工区
     * @param railType 铁路类别
     * **************************************************A********************************************************
     * ******************AA*****************************AB*****************************AC*************************
     * *******AAA***AAB****AAC***AAD**********ABA***ABB****ABC***ABD**********ACA***ACB****ACC***ACD**************
     *
     * 1.当前用户user(总公司、局级、超级管理员)--->deptCode=A,manageDeptCode=[AA,AB] ---->返回AAA,AAB,AAC,AAD,ABA,ABB,ABC,ABD,ACA,ACB,ACC,ACD部门的信息
     * 2.当前用户user(段级用户、分公司用户、及其下级用户)--->deptCode=AA,manageDeptCode=[AAA,AAB,ABA] ---->返回AAA,AAB,AAC,AAD,ABA部门的信息
     * 3.当前用户user(段级用户、分公司用户、及其下级用户)--->deptCode=AA,manageDeptCode=[AAA,AAB,ABA,ACB] ---->返回AAA,AAB,AAC,AAD,ABA,ACB部门的信息
     * @return
     */
    public List<Map<String, Object>> getJcwWorkAreaListByAuth(String railType) {
        return this.getManageDeptList(SysDeptTypeEnum.listJcwWorkArea(),railType);
    }

    /**
     * 获取当前用户所管理的车间
     * @param railType 铁路类别
     * **************************************************A********************************************************
     * ******************AA*****************************AB*****************************AC*************************
     * *******AAA***AAB****AAC***AAD**********ABA***ABB****ABC***ABD**********ACA***ACB****ACC***ACD**************
     * ***AAAA*****AAABA******AACA***********ABAA*********************************ACBA**********************************
     * 1.当前用户user(总公司、局级、超级管理员)--->deptCode=A,manageDeptCode=[AA,AB] ---->返回AAAA、AAABA、AACA部门的信息
     * 2.当前用户user(段级用户、分公司用户、及其下级用户)--->deptCode=AA,manageDeptCode=[AAA,AAB,ABA] ---->返回AAAA、AAABA、AACA、ABAA部门的信息
     * 3.当前用户user(段级用户、分公司用户、及其下级用户)--->deptCode=AA,manageDeptCode=[AAA,AAB,ABA,ACB] ---->返回AAAA、AAABA、AACA、ACBA部门的信息
     * @return
     */
    public List<Map<String, Object>> getJcwWorkShopListByAuth(String railType) {
        return this.getManageDeptList(SysDeptTypeEnum.listJcwWorkshop(),railType);
    }


    /**
     * 根据当前登录用户得到unitDeptCode
     * 当前用户user(总公司、局级、超级管理员)--->unitDeptCode=null
     * 当前用户user(段级用户、分公司用户、及其下级用户)--->deptCode=loginUser.getUnitDeptCode()
     *
     * @return
     */
    public String getUnitDeptCodeByLoginUser(String unitDeptCodeOri) {
        if (StringUtils.isEmpty(unitDeptCodeOri)) {
            UserSso loginUser = AuthHelper.loginUser();
            String unitDeptCode = loginUser.getUnitDeptCode();
            //针对局级用户
            if (AuthConstants.ADMIN_ACCOUNT.equals(loginUser.getUsername())){
                unitDeptCode = null;
            } else if (loginUser.getSuperAccount() == 1) {
                unitDeptCode = null;
            } else if (loginUser.getUnitDeptCode().equals("01")) { //供电部特殊处理
                unitDeptCode = null;
            }
            return unitDeptCode;
        } else {
            return unitDeptCodeOri;
        }
    }

    /**
     * 根据条件获取部门列表
     * @param vo
     * @return
     */
    public List<Map<String, Object>> getList(SysDeptVo vo){
        vo.setUnitDeptCode(getUnitDeptCodeByLoginUser(null));
        return baseMapper.getDeptList(vo);
    }

    /**
     * 获取当前角色管理的部門 树结构
     * @param deptCode 当前用户的部门编码
     * @param isManageDept 是否获取当前用户所管理的部门
     * @return
     */
    public List<TreePo> getManageDeptTree(String deptCode,int isManageDept) {
        UserSso loginUser = AuthHelper.loginUser();
        if (StringUtils.isEmpty(deptCode)){
            deptCode = loginUser.getDeptCode();
        }
        List<String> manageDeptCodeList = new ArrayList<>();
        if (isManageDept==1){
            manageDeptCodeList = loginUser.getManageDeptCodeList();
        }
        List<TreePo> resultList = this.getCommonTreeData(deptCode, manageDeptCodeList);
        return resultList;
    }

    /**
     * @Description //公共樹結構
     * @Date 2022/1/7
     **/
    public List<TreePo> getCommonTreeData(String deptCode, List<String> manageDeptCodeList) {
        //、取出所有部门数据
        HashMap<String, Object> queryMap = new HashMap<>();
        queryMap.put("deptCode", deptCode);
        queryMap.put("manageDeptCodeList", manageDeptCodeList == null ? Stream.of(deptCode).collect(Collectors.toList()) : manageDeptCodeList);
        List<Map<String, Object>> manageDeptList = baseMapper.getManageDeptList(queryMap);
        return this.getCommonTreeData(manageDeptList);
    }

    /**
     * @Description //生成公共树结构
     * @Date 2022/1/7
     **/
    public List<TreePo> getCommonTreeData(List<Map<String, Object>> mapList) {
        List<TreePo> treePos = new ArrayList<>();
        if (CollectionUtils.isEmpty(mapList)) {
            return treePos;
        }
        // 取出父级id 不在结果集中的为第一级
        List<String> deptIdList = mapList.stream().map(map -> map.get("deptId").toString()).collect(Collectors.toList());
        List<Map<String, Object>> oneList = mapList.stream().filter(map -> !deptIdList.contains(ObjectUtil.covToString(map.get("fid")))).collect(Collectors.toList());
        //根据fid分组
        Map<String, List<Map<String, Object>>> groupingMap = mapList.stream().collect(Collectors.groupingBy(e -> e.get("fid").toString()));
        //组装成需要的树
        oneList.forEach(map -> {
            //一级
            TreePo<Object> parentTreePo = new TreePo<>();
            parentTreePo.setId(map.get("deptId").toString());
            parentTreePo.setLabel(map.get("deptName").toString());
            parentTreePo.setCode(ObjectUtil.covToString(map.get("deptNo")));
            if (map.containsKey("dtId")){
                map.put("isSegment", this.checkIsBelowDeptTypeList(map.get("dtId").toString(),
                        Stream.of(SysDeptTypeEnum.SEGMENT.getDeptType()).collect(Collectors.toList())));
                map.put("isWorkShop", this.checkIsBelowDeptTypeList(map.get("dtId").toString(), SysDeptTypeEnum.listWorkshop()));
            }
            parentTreePo.setObj(map);
            //获取子级
            this.getSubTree(parentTreePo, groupingMap);
            treePos.add(parentTreePo);
        });
        return treePos;
    }

    /**
     * @Description //获取子级
     * @Date 2022/1/7
     **/
    private void getSubTree(TreePo treePo, Map<String, List<Map<String, Object>>> groupingMap){
        if (groupingMap.containsKey(treePo.getId())){
            List<Map<String, Object>> mapList = groupingMap.get(treePo.getId());
            ArrayList<TreePo> treePoList = new ArrayList<>();
            mapList.forEach(map -> {
                TreePo<Object> subTreePo = new TreePo<>();
                subTreePo.setId(map.get("deptId").toString());
                subTreePo.setLabel(map.get("deptName").toString());
                subTreePo.setCode(ObjectUtil.covToString(map.get("deptNo")));
                if (map.containsKey("dtId")){
                    map.put("isWorkShop", this.checkIsBelowDeptTypeList(map.get("dtId").toString(), SysDeptTypeEnum.listWorkshop()));
                }
                subTreePo.setObj(map);
                treePoList.add(subTreePo);
                this.getSubTree(subTreePo, groupingMap);
            });
            treePo.setChildren(treePoList);
        }
    }

    /**
     * @Description //dtId部门表类型是否在deptTypeList中。0：不在，1：在
     * @Date 2022/1/7
     **/
    public Integer checkIsBelowDeptTypeList(String dtId, List<String> deptTypeList) {
        if (CollectionUtils.isEmpty(deptTypeList)) {
            return 0;
        }
        List<String> dtIdList = Stream.of(dtId.split(",")).collect(Collectors.toList());
        Long count = dtIdList.stream().filter(dtIdTemp -> (deptTypeList.indexOf(dtIdTemp)>-1)).count();
        return (count>0) ? 1 : 0;
    }

    /**
     * @return java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
     * @Author jchen
     * @Date: 14:28 2021/7/16
     * @Description: 如果deptCode是当前登入人的所属部门、或者下属部门（那么查询结果为查询deptCode对应的部门+deptCode对应的下属部门）
     * 如果deptCOde是当前登入人的角色管理权限分配的部门，那么查询结果为deptCode对应的部门+（在角色权限那里勾选的deptCode对应的下级部门。如果没有勾选下级部门，这里就没有）
     * @Param [queryMap]
     **/
    public List<Map<String, Object>> findDeptAndChildrenList(Map<String, Object> queryMap) {
        List<Map<String, Object>> resultMapList = new ArrayList<>();
        String queryDeptCode = queryMap.get("queryDeptCode") == null ? "" : queryMap.get("queryDeptCode").toString();
        String loginDeptCode = queryMap.get("loginDeptCode") == null ? "" : queryMap.get("loginDeptCode").toString();
        List<String> manageDeptCodeList = queryMap.get("manageDeptCodeList") == null ? null : (List<String>) queryMap.get("manageDeptCodeList");
        if (org.apache.commons.lang3.StringUtils.isEmpty(queryDeptCode)) {
            return resultMapList;
        }
        //1、判断queryDeptCode 是否是loginDeptCode的子
        Integer checkCount = baseMapper.checkThisDeptIsBelongDeptChild(queryDeptCode, loginDeptCode);
        if (checkCount > 0) {
            resultMapList = baseMapper.getDeptAllChildAndMain(queryDeptCode);
            return resultMapList;
        }
        //2、说明是管理部门的数据(如果管理部门没有数据)
        if (CollectionUtils.isEmpty(manageDeptCodeList)) {
            SysDeptVo vo = new SysDeptVo();
            vo.setDeptCode(queryDeptCode);
            Map<String, Object> map = baseMapper.getDeptByFilter(vo);
            if (CollectionUtils.isEmpty(map)) {
                return resultMapList;
            }
            resultMapList.add(map);
            return resultMapList;
        }

        //3、说明是管理部门的数据(管理有数据)
        resultMapList = baseMapper.getManageDeptAllChildAndMain(queryDeptCode, manageDeptCodeList);
        return resultMapList;
    }

    public List<String> getQueryDeptIdList(String queryDeptCode){
        List<String> queryDeptIdList = new ArrayList<>();
        UserSso loginUser = AuthHelper.loginUser();
        if(org.apache.commons.lang3.StringUtils.isEmpty(queryDeptCode)){
            HashMap<String, Object> queryMap = new HashMap<>();
            queryMap.put("deptCode", loginUser.getDeptCode());
            queryMap.put("manageDeptCodeList", loginUser.getManageDeptCodeList() == null ? Stream.of(loginUser.getDeptCode()).collect(Collectors.toList()) : loginUser.getManageDeptCodeList());
            queryDeptIdList = baseMapper.getManageDeptIdList(queryMap);
            return queryDeptIdList;
        }
        Map<String,Object> queryMap = new HashMap<>();
        queryMap.put("queryDeptCode",queryDeptCode);
        queryMap.put("loginDeptCode",loginUser.getDeptCode());
        queryMap.put("manageDeptCodeList",loginUser.getManageDeptCodeList());
        List<Map<String,Object>> mapList = findDeptAndChildrenList(queryMap);
        if(org.apache.commons.collections4.CollectionUtils.isEmpty(mapList)){
            return queryDeptIdList;
        }
        queryDeptIdList = mapList.stream().map(map->map.get("deptId").toString()).collect(Collectors.toList());
        return queryDeptIdList;

    }

    public IPage<Map<String,Object>> pageList4Brain(SysDeptVo vo){
        return baseMapper.pageList4Brain(vo.page(),vo);
    }

}
